package com.qf.data.service.impl;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qf.common.bean.Pages;
import com.qf.common.constant.CacheConstant;
import com.qf.common.dto.DeviceModelValueDto;
import com.qf.common.model.DeviceModelValue;
import com.qf.data.service.DeviceModelValueService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * @author 千锋健哥
 */
@Slf4j
@Service
public class DeviceModelValueServiceImpl implements DeviceModelValueService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public void saveDeviceModelValue(DeviceModelValue deviceModelValue) {
        //1. 判断对象不为空
        if (deviceModelValue == null) {
            log.info("center-data服务, 设备传感器数据为空, 不允许保存!");
            return;
        }
        if (StringUtils.isEmpty(deviceModelValue.getDevice())
                || StringUtils.isEmpty(deviceModelValue.getProduct_key())) {
            log.info("center-data服务, 设备传感器数据设备key和产品key不可以为空, 否则不允许保存!" + deviceModelValue);
            return;
        }
        //2. 声明mongodb集合, device_value_产品key
        String collection = CacheConstant.Entity.DEVICE + CacheConstant.Suffix.VALUE + "_" + deviceModelValue.getProduct_key();

        //3. 给集合创建索引(增加查询效率)
        createModelValueIndex(collection);

        //4. 将文档保存到集合中
        mongoTemplate.insert(deviceModelValue, collection);
    }

    @Override
    public Page<DeviceModelValue> list(DeviceModelValueDto dto) {
        Page<DeviceModelValue> deviceModelValuePage = new Page<>();

        //1. 创建查询条件对象
        Criteria criteria = new Criteria();
        Query query = new Query(criteria);

        //2. 设置查询条件
        //判断如果租户id不为空, 根据租户id查询
        if (StringUtils.isNotEmpty(dto.getTenant_id())) {
            criteria.and("tenant_id").is(dto.getTenant_id());
        }
        //判断如果产品key不为空, 根据产品key查询
        if (StringUtils.isNotEmpty(dto.getProduct_key())) {
            criteria.and("product_key").is(dto.getProduct_key());
        }
        //判断如果设备key不为空, 根据设备key查询
        if (StringUtils.isNotEmpty(dto.getDevice())) {
            criteria.and("device").is(dto.getDevice());
        }
        //根据时间范围查询
        if (dto.getPage().getStartTime() > 0 && dto.getPage().getEndTime() > 0) {
            criteria.and("createTime").gte(new Date(dto.getPage().getStartTime()))
                    .lte(new Date(dto.getPage().getEndTime()));
        }

        //3. 执行查询并返回结果
        //设置查询的集合名称
        String collection = CacheConstant.Entity.DEVICE + CacheConstant.Suffix.VALUE + "_" + dto.getProduct_key();

        //统计mongodb根据这个查询条件, 满足条件的数据总数
        long count = mongoTemplate.count(query, collection);

        //分页
        Pages page = dto.getPage();
        //计算从第几条开始查询
        long size = page.getSize() * (page.getCurrent() - 1);
        //设置从第几条开始查询
        query.limit((int) page.getSize()).skip(size);

        //排序, 第一个参数: 降序或者升序, 第二参数: 排序字段名
        query.with(Sort.by(Sort.Direction.DESC, "createTime"));

        //执行查询
        List<DeviceModelValue> list = mongoTemplate.find(query, DeviceModelValue.class, collection);

        //封装分页对象
        deviceModelValuePage
                .setCurrent(page.getCurrent())
                .setSize(page.getSize())
                .setTotal(count)
                .setRecords(list);

        return deviceModelValuePage;
    }

    /**
     * 创建集合中的索引, 索引可以加快查询效率
     * @param collection
     */
    private void createModelValueIndex(String collection) {
        //创建设备key索引
        Index deviceIndex = new Index();
        deviceIndex.background()
                //第一参数, 索引字段名称, 第二参数: 排序规则
                .on("device", Sort.Direction.DESC)
                //索引名字, 随便起名, 不可以重名
                .named("index_device_key");
        mongoTemplate.indexOps(collection).ensureIndex(deviceIndex);

        //创建产品key索引
        Index productIndex = new Index();
        productIndex.background()
                //第一参数, 索引字段名称, 第二参数: 排序规则
                .on("product_key", Sort.Direction.DESC)
                //索引名字, 随便起名, 不可以重名
                .named("index_product_key");
        mongoTemplate.indexOps(collection).ensureIndex(productIndex);

        //创建租户id索引
        Index tenantIndex = new Index();
        tenantIndex.background()
                //第一参数, 索引字段名称, 第二参数: 排序规则
                .on("tenant_id", Sort.Direction.DESC)
                //索引名字, 随便起名, 不可以重名
                .named("index_tenant_id");
        mongoTemplate.indexOps(collection).ensureIndex(tenantIndex);

        //创建设备key索引
        Index createTimeIndex = new Index();
        createTimeIndex.background()
                //第一参数, 索引字段名称, 第二参数: 排序规则
                .on("createTime", Sort.Direction.DESC)
                //索引名字, 随便起名, 不可以重名
                .named("index_create_time");
        mongoTemplate.indexOps(collection).ensureIndex(createTimeIndex);
    }

}
